import {strict as assert} from 'assert'
import {dump} from './_foot'

export ARGS = new Map()
export ARGS_N = new Map()

export CMD = {
  HI : 1
  Q : 2
  A : 3
  PK : 4
}
AsyncFunction = `(async ()=>{})`.constructor

export default new Proxy(
  {}
  {
    get: (obj, prop)=>
      if prop of obj
        return obj[prop]
      assert(prop of CMD)
      [cmd,n] = ARGS_N.get(prop)

      obj[prop] = func = (...args)=>

        body = args[...n]
        li = args[n..]
        li.unshift(cmd)

        body.push dump(li)

        return Buffer.concat body
      func
  }
)

export $ = (func)=>
  if func instanceof AsyncFunction
    f = ->
      try
        r = await func(...arguments)
      catch err
        console.trace err
        return
      {length} = arguments
      {address,port} = arguments[length-1]
      if r != undefined
        @send(
          r
          port
          address
        )
      return
  else
    f = ->
      try
        r = func(...arguments)
      catch err
        console.trace err
        return
      {length} = arguments
      {address,port} = arguments[length-1]
      if r != undefined
        @send(
          r
          port
          address
        )
      return
  return f

export CALL = new Proxy(
  CMD
  {
    get:(self, attr)=>
      cmd = self[attr]
      (...args)=>
        func = args.pop()
        ARGS.set cmd, [
          args
          $ func
        ]
        ARGS_N.set attr, [cmd, args.length+1]
        return
  }
)
